/*
 * Copyright (c) 2025 CAX Conversion Project
 */
package com.comac.ins.bomt.service.impl;

import com.comac.ins.bomt.common.enums.ModelStatusChangeStatisticTypeEnum;
import com.comac.ins.bomt.domain.*;
import com.comac.ins.bomt.domain.vo.*;
import com.comac.ins.bomt.repository.BomRepository;
import com.comac.ins.bomt.service.BomCoreService;
import com.comac.ins.bomt.utils.BomCoreUtil;
import com.comac.ins.bomt.utils.BomVersionUtil;
import com.comac.ins.common.core.domain.model.LoginUser;
import com.comac.ins.common.core.utils.BizAssertUtil;
import com.comac.ins.common.core.utils.MapstructUtils;
import com.comac.ins.common.json.utils.JsonUtils;
import com.comac.ins.common.mybatis.helper.BaseEntityHelper;
import jodd.util.StringUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.text.MessageFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicLong;
import java.util.stream.Collectors;

import static com.comac.ins.bomt.common.enums.StrengthChangeStatisticTypeEnum.*;
import static com.comac.ins.bomt.common.enums.StrengthChangeStatisticTypeEnum.CHANGE;

/**
 * Bom核心转化服务实现(基于原VBA逻辑翻写，原逻辑很多较难理解，不敢贸然进行优化，因此翻写基本与原逻辑一一对应)
 *
 * @author zhanghongyi
 * @date 2024 /8/28
 * @description BomConvertServiceImpl
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class BomCoreServiceImpl implements BomCoreService {

    private final BomRepository bomRepository;

    @Value("${bom.codePath.joinChar:,}")
    private String fullCodePathJoinChar;


    @Override
    public Map<String, List<DetailStandardBomVo>> convertOriginToStandard(LoginUser loginUser, List<DetailOriginalBomVo> originalBomVos, Map<String, String> reverseGroupConfig, List<String> deleteWords, String aircraftModel, String track, List<String> noticeMessages) {
        Set<String> noticeSet = new HashSet<>();
        Map<String, List<DetailOriginalBomVo>> groupedVos = originalBomVos.stream().filter(vo -> {
            if(reverseGroupConfig.containsKey(vo.getSection())){
                return true;
            } else {
                noticeSet.add(MessageFormat.format("清单内存在未配置部段:{0}，请检查", vo.getSection()));
                return false;
            }
        }).collect(Collectors.groupingBy(vo -> reverseGroupConfig.get(vo.getSection()), LinkedHashMap::new, Collectors.toList()));
        noticeMessages.addAll(noticeSet);
        Map<String, List<DetailStandardBomVo>> groupedStandardVos = new LinkedHashMap<>();
        for (Map.Entry<String, List<DetailOriginalBomVo>> entry : groupedVos.entrySet()) {
            Stack<DetailOriginalBomVo> parentStack = new Stack<>();
            List<DetailStandardBomVo> detailStandardBomVos = new ArrayList<>();
            AtomicLong ord = new AtomicLong();
            for (DetailOriginalBomVo originalBomVo : entry.getValue()) {
                if (CollectionUtils.isNotEmpty(parentStack) && Integer.parseInt(originalBomVo.getLevel()) <= Integer.parseInt(parentStack.peek().getLevel())) {
                    int curLevel = Integer.parseInt(originalBomVo.getLevel());
                    while (CollectionUtils.isNotEmpty(parentStack) && Integer.parseInt(parentStack.peek().getLevel()) >= curLevel) {
                        parentStack.pop();
                    }
                }
                parentStack.push(originalBomVo);
                String fullCodePath = StringUtils.join(parentStack.stream().map(DetailOriginalBomVo::getCode).toList(), fullCodePathJoinChar);
                DetailStandardBomVo detailStandardBomVo = DetailStandardBomVo.createFromOriginalBom(originalBomVo, aircraftModel, fullCodePath, entry.getKey(), track);
                detailStandardBomVo.setOrd(ord.getAndIncrement());
                if ((!StringUtils.equals(detailStandardBomVo.getLevel(), "1")) && StringUtils.containsAny(detailStandardBomVo.getName(), deleteWords.toArray(new String[0]))) {
                    log.debug("match keyword,code:{}: name:{} level:{} is deleted", detailStandardBomVo.getCode(), detailStandardBomVo.getName(), detailStandardBomVo.getLevel());
                    //非根节点且名称包含关键词的抛弃掉
                    continue;
                }
                detailStandardBomVos.add(detailStandardBomVo);
            }
            groupedStandardVos.put(entry.getKey(), detailStandardBomVos);
            log.info("standard group:{} size:{}", entry.getKey(), detailStandardBomVos.size());
        }
        BizAssertUtil.notEmpty(groupedStandardVos, "生成的标准装机清单为空");
        return groupedStandardVos;
    }

    @Override
    public List<DetailStrengthBom> convertStandardToStrength(LoginUser loginUser, List<DetailStandardBom> standardBomDetails, List<String> deleteWords) {
        AtomicLong ord = new AtomicLong();
        List<DetailStrengthBom> result = new ArrayList<>();
        Integer gCnt = 1;
        String gLevel = "2";
        for (int i = 0; i < standardBomDetails.size(); i++) {
            DetailStandardBom detail = standardBomDetails.get(i);
            String code = StringUtils.split(detail.getCode(), ".")[0];
            if (checkNotTargetItem(detail)) {
                //忽略非目标项
                continue;
            }
            if (checkG40Begin(detail)) {
                gCnt = detail.getCnt();
                gLevel = detail.getLevel();
                i++;
                detail = standardBomDetails.get(i);
            }
            if (checkG40End(detail, gLevel, code)) {
                gCnt = 1;
                gLevel = detail.getLevel();
            }
            for (int j = 0; j < gCnt * detail.getCnt(); j++) {
                //Q:VBA原版逻辑，比较费解，g40begin后的第一条使用g40begin的code覆盖
                detail.setCode(code);
                result.add(convertDetailStandardToStrength(loginUser, ord.getAndIncrement(), detail));
            }
        }
        //排除命中删除关键字的条目
        result = result.stream().filter(detail -> {
            boolean f = (!StringUtils.containsAny(detail.getName(), deleteWords.toArray(new String[0]))) || StringUtils.equals(detail.getLevel(), "1");
            if (!f) {
                log.debug("match keyword, code:{}: name:{} level:{} is deleted", detail.getCode(), detail.getName(), detail.getLevel());
            }
            return f;
        }).toList();
        return result;
    }

    @Override
    public DetailStrengthBom convertDetailStandardToStrength(LoginUser loginUser, Long ord, DetailStandardBom detail) {
        DetailStrengthBom item = new DetailStrengthBom();
        item.setCode(StringUtils.split(detail.getCode(), ".")[0]);
        item.setLevel(StringUtils.equals("1", detail.getLevel()) ? "1" : "1.1");
        item.setName(detail.getName());
        item.setFullCodePath(detail.getFullCodePath());
        item.setVersion(detail.getVersion());
        item.setVersionNum("1");
        item.setOrd(ord);
        item.setAta(detail.getAta());
        item.setGroupType(detail.getGroupType());
        item.setSubGroupType(detail.getSubGroupType());
        item.setAircraftModel(detail.getAircraftModel());
        item.setTrack(detail.getTrack());
        item.setSubTrack(detail.getSubTrack());
        item.setStandardDetailId(detail.getId());
        BaseEntityHelper.fillCreateByAndUpdateBy(detail, loginUser);
        return item;
    }


    @Override
    public SummaryStatusStrengthChangeVo compareStatusStrength(LoginUser loginUser, BomInfo bomInfo, List<DetailStrengthStandardChange> strengthChangeDetails, List<DetailModelStatus> modelStatusDetails) {
        //进行对比
        SummaryStatusStrengthChangeVo result = new SummaryStatusStrengthChangeVo();
        List<DetailStatusStrengthChange> oldList = modelStatusDetails.stream().map(detail -> {
            DetailStatusStrengthChange change = new DetailStatusStrengthChange();
            BeanUtils.copyProperties(detail, change);
            change.setTrack(bomInfo.getTrack());
            change.setAircraftModel(bomInfo.getAircraftModel());
            change.setAta(bomInfo.getAta());
            change.setGroupType(bomInfo.getGroupType());
            //默认全删除
            change.setChangeType(ModelStatusChangeStatisticTypeEnum.DELETE.getType());
            return change;
        }).collect(Collectors.toList());
        Map<String, List<DetailStatusStrengthChange>> groupedOldMap = BomCoreUtil.groupByLevelCode(oldList);
        //排除已删除的
        Map<String, List<DetailStrengthStandardChange>> groupedNewMap = BomCoreUtil.groupByLevelCode(strengthChangeDetails.stream().filter(item -> !StringUtils.equals(DELETE.getType(), item.getChangeType())).toList());
        for (Map.Entry<String, List<DetailStrengthStandardChange>> newEntry : groupedNewMap.entrySet()) {
            compareStatusStrengthGroupItem(loginUser, newEntry.getKey(), newEntry.getValue(), groupedOldMap.getOrDefault(newEntry.getKey(), new ArrayList<>()), result.getChangeDetailStringMap(), oldList);
        }
        result.setChangeDetailList(MapstructUtils.convert(oldList, DetailStatusStrengthChangeVo.class));
        //重新分配序号
        AtomicLong ord = new AtomicLong(0);
        result.getChangeDetailList().forEach(item -> item.setOrd(ord.getAndIncrement()));
        //统计摘要
        Map<String, List<DetailStatusStrengthChangeVo>> groupMap = result.getChangeDetailList().stream().collect(Collectors.groupingBy(DetailStatusStrengthChangeVo::getChangeType));
        for (Map.Entry<String, List<DetailStatusStrengthChangeVo>> entry : groupMap.entrySet()) {
            result.getChangeCountMap().put(entry.getKey(), entry.getValue().size());
        }
        result.setVersions(BomVersionUtil.getVersions(result.getChangeDetailList()));
        //统计删除的部分
        for (DetailStatusStrengthChangeVo item : result.getChangeDetailList()) {
            if (StringUtils.equals(ModelStatusChangeStatisticTypeEnum.DELETE.getType(), item.getChangeType())) {
                String strDelete = result.getChangeDetailStringMap().getOrDefault(ModelStatusChangeStatisticTypeEnum.DELETE.getType(), "");
                strDelete = MessageFormat.format("{0}{1}\t{2}\t{3}\n", strDelete, StringUtils.split(item.getFullCodePath(), ",")[0], item.getCode(), item.getVersion());
                result.getChangeDetailStringMap().put(ModelStatusChangeStatisticTypeEnum.DELETE.getType(), strDelete);
            }
        }

        log.info("track:{},statusStrengthCompareCount:{}", bomInfo.getTrack(), JsonUtils.toJsonString(result.getChangeCountMap()));
        return result;
    }

    /**
     * 判断是否为目标项
     *
     * @param detail the detail
     * @return the boolean
     */
    private boolean checkNotTargetItem(DetailStandardBom detail) {
        String code = StringUtils.split(detail.getCode(), ".")[0];
        boolean isTargetItem = code.startsWith("R") || StringUtils.isNumeric(code.substring(0, Math.min(code.length(), 4)));
        return !isTargetItem;
    }

    /**
     * 判断是否为G40开始
     *
     * @param detail the detail
     * @return the boolean
     */
    private boolean checkG40Begin(DetailStandardBom detail) {
        String code = StringUtils.split(detail.getCode(), ".")[0];
        if (StringUtils.equals(detail.getAircraftModel(), "C919")) {
            //C919
            String conditionS = code.substring(code.length() - 2);
            if (StringUtils.isNumeric(conditionS)) {
                int conditionI = Integer.parseInt(conditionS);
                return conditionI >= 40 && conditionI < 50 && !code.startsWith("R");
            } else {
                return false;
            }
        } else {
            //C929
            String conditionS = code.substring(code.length() - 3);
            if (StringUtils.isNumeric(conditionS)) {
                int conditionI = Integer.parseInt(conditionS);
                return conditionI >= 400 && conditionI < 500 && !code.startsWith("R");
            } else {
                return false;
            }
        }
    }

    /**
     * 是否G40结束
     *
     * @param detail     the detail
     * @param beginLevel the begin level
     * @return the boolean
     */
    private boolean checkG40End(DetailStandardBom detail, String beginLevel, String code) {
        return StringUtils.equals(detail.getLevel(), beginLevel) || code.startsWith("R");
    }

    private void compareStatusStrengthGroupItem(LoginUser loginUser, String groupKey, List<DetailStrengthStandardChange> newDetails, List<DetailStatusStrengthChange> oldDetails, Map<String, String> resultChangeDetailStringMap, List<DetailStatusStrengthChange> resultList) {
        DetailStrengthStandardChange newG20 = newDetails.get(0);
        String newG20Code = StringUtils.split(newG20.getCode(), ".")[0];
        int insertPos = resultList.size();
        if (CollectionUtils.isNotEmpty(oldDetails)) {
            insertPos = resultList.indexOf(oldDetails.get(oldDetails.size() - 1)) + 1;
        }
        String oldG20Code = null;
        if (CollectionUtils.isNotEmpty(oldDetails)) {
            DetailStatusStrengthChange oldG20 = oldDetails.get(0);
            oldG20Code = StringUtils.split(oldG20.getCode(), ".")[0];
            oldG20.setStandardDetailId(newG20.getStandardDetailId());
            if (!StringUtils.equals(newG20.getCode(), oldG20.getCode())) {
                //组件升号
                oldG20.setChangeType(ModelStatusChangeStatisticTypeEnum.NUMBER.getType());

                String strNumber = resultChangeDetailStringMap.getOrDefault(ModelStatusChangeStatisticTypeEnum.NUMBER.getType(), "");
                strNumber = MessageFormat.format("{0}{1}\t              \t{2}\t升号到\t{3}\t              \t{4}\n", strNumber, oldG20.getCode(), oldG20.getVersion(), newG20.getCode(), newG20.getVersion());
                resultChangeDetailStringMap.put(ModelStatusChangeStatisticTypeEnum.NUMBER.getType(), strNumber);
            } else if (StringUtils.equals(newG20.getVersion(), oldG20.getVersion())) {
                //版本相同
                oldG20.setChangeType(ModelStatusChangeStatisticTypeEnum.SAME.getType());
            } else if (StringUtils.equals(newG20.getVersionNum(), "1")) {
                //建模升版
                oldG20.setChangeType(ModelStatusChangeStatisticTypeEnum.MODEL_UPGRADE.getType());
                String strModelUp = resultChangeDetailStringMap.getOrDefault(ModelStatusChangeStatisticTypeEnum.MODEL_UPGRADE.getType(), "");
                strModelUp = MessageFormat.format("{0}{1}\t              \t{2}\t建模升版到\t{3}\n", strModelUp, oldG20.getCode(), oldG20.getVersion(), newG20.getVersion());
                resultChangeDetailStringMap.put(ModelStatusChangeStatisticTypeEnum.MODEL_UPGRADE.getType(), strModelUp);
            } else {
                //复制升版
                oldG20.setChangeType(ModelStatusChangeStatisticTypeEnum.COPY_UPGRADE.getType());
                String strCopyUp = resultChangeDetailStringMap.getOrDefault(ModelStatusChangeStatisticTypeEnum.COPY_UPGRADE.getType(), "");
                strCopyUp = MessageFormat.format("{0}{1}\t              \t{2}\t复制升版到\t{3}\n", strCopyUp, oldG20.getCode(), oldG20.getVersion(), newG20.getVersion());
                resultChangeDetailStringMap.put(ModelStatusChangeStatisticTypeEnum.COPY_UPGRADE.getType(), strCopyUp);
            }
        } else {
            //新增
            DetailStatusStrengthChange newAdd = new DetailStatusStrengthChange();
            BeanUtils.copyProperties(newG20, newAdd);
            newAdd.setChangeType(ModelStatusChangeStatisticTypeEnum.ADD.getType());
            resultList.add(insertPos, newAdd);
            insertPos++;
            String strNewAdd = resultChangeDetailStringMap.getOrDefault(ModelStatusChangeStatisticTypeEnum.ADD.getType(), "");
            strNewAdd = MessageFormat.format("{0}{1}\t{2}\n", strNewAdd, newG20.getCode(), newG20.getVersion());
            resultChangeDetailStringMap.put(ModelStatusChangeStatisticTypeEnum.ADD.getType(), strNewAdd);
        }
        for (DetailStrengthStandardChange newDetail : newDetails.subList(1, newDetails.size())) {
            boolean found = false;
            if (CollectionUtils.isNotEmpty(oldDetails)) {
                String newG70Code = StringUtils.split(newDetail.getCode(), ".")[0];
                String newG70Code1 = newG70Code.substring(0, newG70Code.length() - 1);
                for (DetailStatusStrengthChange old : oldDetails.subList(1, oldDetails.size())) {
                    if (StringUtils.equals(ModelStatusChangeStatisticTypeEnum.DELETE.getType(), old.getChangeType())) {
                        if (StringUtils.containsIgnoreCase(old.getCode(), "rbe")) {
                            old.setChangeType(ModelStatusChangeStatisticTypeEnum.NUMBER.getType());
                        }
                        String oldG70Code = StringUtils.split(old.getCode(), ".")[0];
                        String oldG70Code1 = oldG70Code.substring(0, oldG70Code.length() - 1);
                        if (StringUtils.equals(newG70Code1, oldG70Code1)) {
                            found = true;
                            if (!StringUtils.equals(newG70Code, oldG70Code)) {
                                //升号
                                old.setChangeType(ModelStatusChangeStatisticTypeEnum.NUMBER.getType());
                                String strNumber = resultChangeDetailStringMap.getOrDefault(ModelStatusChangeStatisticTypeEnum.NUMBER.getType(), "");
                                strNumber = MessageFormat.format("{0}{1}\t{2}\t{3}\t升号到\t{4}\t{5}\t{6}\n", strNumber, oldG20Code, oldG70Code, old.getVersion(), newG20Code, newG70Code, newDetail.getVersion());
                                resultChangeDetailStringMap.put(ModelStatusChangeStatisticTypeEnum.NUMBER.getType(), strNumber);
                            } else if (StringUtils.equals(newDetail.getVersion(), old.getVersion())) {
                                //版本相同
                                old.setChangeType(ModelStatusChangeStatisticTypeEnum.SAME.getType());
                            } else if (StringUtils.equals(newDetail.getVersionNum(), "1")) {
                                //建模升版
                                old.setChangeType(ModelStatusChangeStatisticTypeEnum.MODEL_UPGRADE.getType());
                                String strModelUp = resultChangeDetailStringMap.getOrDefault(ModelStatusChangeStatisticTypeEnum.MODEL_UPGRADE.getType(), "");
                                strModelUp = MessageFormat.format("{0}{1}\t{2}\t{3}\t建模升版到\t{4}\n", strModelUp, oldG20Code, oldG70Code, old.getVersion(), newDetail.getVersion());
                                resultChangeDetailStringMap.put(ModelStatusChangeStatisticTypeEnum.MODEL_UPGRADE.getType(), strModelUp);
                            } else {
                                //复制升版
                                old.setChangeType(ModelStatusChangeStatisticTypeEnum.COPY_UPGRADE.getType());
                                String strCopyUp = resultChangeDetailStringMap.getOrDefault(ModelStatusChangeStatisticTypeEnum.MODEL_UPGRADE.getType(), "");
                                strCopyUp = MessageFormat.format("{0}{1}\t{2}\t{3}\t复制升版到\t{4}\n", strCopyUp, oldG20Code, oldG70Code, old.getVersion(), newDetail.getVersion());
                                resultChangeDetailStringMap.put(ModelStatusChangeStatisticTypeEnum.COPY_UPGRADE.getType(), strCopyUp);
                            }
                            break;
                        }
                    }
                }
            }
            if (!found) {
                //新增
                DetailStatusStrengthChange newAdd = new DetailStatusStrengthChange();
                BeanUtils.copyProperties(newDetail, newAdd);
                newAdd.setChangeType(ModelStatusChangeStatisticTypeEnum.ADD.getType());
                resultList.add(insertPos, newAdd);
                insertPos++;
                String strNewAdd = resultChangeDetailStringMap.getOrDefault(ModelStatusChangeStatisticTypeEnum.ADD.getType(), "");
                strNewAdd = MessageFormat.format("{0}{1}\t{2}\t{3}\n", strNewAdd, newG20Code, StringUtils.split(newAdd.getCode(), ".")[0], newAdd.getVersion());
                resultChangeDetailStringMap.put(ModelStatusChangeStatisticTypeEnum.ADD.getType(), strNewAdd);
            }
        }
    }

    @Override
    public SummaryStrengthStandardChangeVo compareStrengthStandard(LoginUser loginUser, BomInfo bomInfo, List<DetailStandardBom> standardBomDetails, List<DetailStrengthBom> strengthBomDetails) {
        SummaryStrengthStandardChangeVo result = new SummaryStrengthStandardChangeVo();
        List<DetailStrengthStandardChange> oldList = strengthBomDetails.stream().map(strengthDetail -> {
            DetailStrengthStandardChange change = new DetailStrengthStandardChange();
            BeanUtils.copyProperties(strengthDetail, change);
            change.setId(null);
            change.setTrack(bomInfo.getTrack());
            //默认全为删除
            change.setChangeType(DELETE.getType());
            return change;
        }).collect(Collectors.toList());
        Map<String, List<DetailStrengthStandardChange>> strengthGroup = BomCoreUtil.groupByLevelCode(oldList);
        Map<String, List<DetailStandardBom>> standardGroup = BomCoreUtil.groupByLevelCode(standardBomDetails);
        for (Map.Entry<String, List<DetailStandardBom>> standardEntry : standardGroup.entrySet()) {
            compareStrengthStandardGroupItem(loginUser, standardEntry.getKey(), standardEntry.getValue(), strengthGroup.getOrDefault(standardEntry.getKey(), new ArrayList<>()), result.getChangeCountMap(), oldList);
        }
        result.setChangeDetailList(MapstructUtils.convert(oldList, DetailStrengthStandardChangeVo.class));
        //统计删除的
        result.getChangeCountMap().put(DELETE.getType(), oldList.stream().filter(item -> item.getChangeType().equals(DELETE.getType())).toList().size());
        //重新分配序号
        AtomicLong ord = new AtomicLong(0);
        result.getChangeDetailList().forEach(item -> item.setOrd(ord.getAndIncrement()));
        result.setVersions(BomVersionUtil.getVersions(result.getChangeDetailList()));
        log.info("track:{},strengthStandardCompareCount:{}", bomInfo.getTrack(), JsonUtils.toJsonString(result.getChangeCountMap()));
        return result;
    }

    private void compareStrengthStandardGroupItem(LoginUser loginUser, String groupKey, List<DetailStandardBom> standardBomDetails, List<DetailStrengthStandardChange> strengthBomDetails, Map<String, Integer> resultChangeCountMap, List<DetailStrengthStandardChange> resultList) {
        Integer gCnt = 1;
        String gLevel = "2";
        int insertPos = resultList.size();
        if (CollectionUtils.isNotEmpty(strengthBomDetails)) {
            insertPos = resultList.indexOf(strengthBomDetails.get(strengthBomDetails.size() - 1)) + 1;
        }
        for (int i = 0; i < standardBomDetails.size(); i++) {
            DetailStandardBom standardDetail = standardBomDetails.get(i);
            String code = standardDetail.getCode();
            if (checkNotTargetItem(standardDetail)) {
                continue;
            }
            if (checkG40Begin(standardDetail)) {
                gCnt = standardDetail.getCnt();
                gLevel = standardDetail.getLevel();
                i++;
                standardDetail = standardBomDetails.get(i);
            }
            if (checkG40End(standardDetail, gLevel, code)) {
                gCnt = 1;
                gLevel = standardDetail.getLevel();
            }
            for (int j = 0; j < gCnt * standardDetail.getCnt(); j++) {
                boolean found = false;
                String standardCodeStr = getCodeStr(code, standardDetail.getLevel(), standardDetail.getAircraftModel());
                String standardCodeNum = getCodeNum(code, standardDetail.getLevel(), standardDetail.getAircraftModel());
                for (DetailStrengthStandardChange strengthDetail : strengthBomDetails) {
                    if (!StringUtils.equals(DELETE.getType(), strengthDetail.getChangeType())) {
                        continue;
                    }
                    String strengthCodeStr = getCodeStr(strengthDetail.getCode(), strengthDetail.getLevel(), strengthDetail.getAircraftModel());
                    String strengthCodeNum = getCodeNum(strengthDetail.getCode(), strengthDetail.getLevel(), strengthDetail.getAircraftModel());
                    if (StringUtils.equals(standardCodeStr, strengthCodeStr)) {
                        found = true;
                        resultChangeCountMap.put(CHECKED.getType(), resultChangeCountMap.getOrDefault(CHECKED.getType(), 0) + 1);
                        strengthDetail.setChangeType(CHECKED.getType());
                        if (!StringUtils.equals(standardCodeNum, strengthCodeNum)) {
                            //换号
                            String comment = strengthDetail.getCode().substring(strengthDetail.getCode().length() - 3) + ":" + strengthDetail.getVersion() + strengthDetail.getVersionNum() + " ;";
                            if (StringUtils.isNotBlank(strengthDetail.getNote())) {
                                comment = strengthDetail.getNote() + "\n" + comment;
                            }
                            //Q:此处VBA是直接赋值的标准装机清单层级，疑似bug，这里都处理为1或1.1
                            strengthDetail.setLevel(StringUtil.equals("1", standardDetail.getLevel()) ? "1" : "1.1");
                            strengthDetail.setCode(code);
                            strengthDetail.setName(standardDetail.getName());
                            strengthDetail.setChangeType(NUMBER.getType());
                            strengthDetail.setVersion(standardDetail.getVersion());
                            strengthDetail.setVersionNum("1");
                            strengthDetail.setNote(comment);
                            bomRepository.updateStrengthDetailCommentByStandardDetail(standardDetail, comment);
                            resultChangeCountMap.put(NUMBER.getType(), resultChangeCountMap.getOrDefault(NUMBER.getType(), 0) + 1);
                            break;
                        } else if (StringUtils.equals(standardDetail.getVersion(), strengthDetail.getVersion())) {
                            //版本一致
                            strengthDetail.setChangeType(SAME.getType());
                            strengthDetail.setName(standardDetail.getName());
                            resultChangeCountMap.put(SAME.getType(), resultChangeCountMap.getOrDefault(SAME.getType(), 0) + 1);
                            break;
                        } else {
                            //升版
                            strengthDetail.setChangeType(CHANGE.getType());
                            strengthDetail.setVersion(standardDetail.getVersion());
                            strengthDetail.setVersionNum("1");
                            strengthDetail.setName(standardDetail.getName());
                            resultChangeCountMap.put(CHANGE.getType(), resultChangeCountMap.getOrDefault(CHANGE.getType(), 0) + 1);
                            break;
                        }
                    }
                }
                if (!found) {
                    //新增
                    DetailStrengthStandardChange change = new DetailStrengthStandardChange();
                    BeanUtils.copyProperties(convertDetailStandardToStrength(loginUser, -1L, standardDetail), change);
                    change.setChangeType(ADD.getType());
                    change.setCode(code);
                    resultList.add(insertPos, change);
                    insertPos++;
                    resultChangeCountMap.put(ADD.getType(), resultChangeCountMap.getOrDefault(ADD.getType(), 0) + 1);
                }
            }
        }
    }

    private String getCodeStr(String code, String level, String aircraftModel) {
        if (StringUtils.equals("C919", aircraftModel)) {
            //C919
            return StringUtils.equals(level, "1") ? code.substring(0, code.length() - 2) : code.substring(0, code.length() - 1);
        } else {
            //C929
            return code.substring(0, code.length() - 1);
        }
    }

    private String getCodeNum(String code, String level, String aircraftModel) {
        if (StringUtils.equals("C919", aircraftModel)) {
            //C919
            return StringUtils.equals(level, "1") ? code.substring(code.length() - 2) : code.substring(code.length() - 1);
        } else {
            //C929
            return code.substring(code.length() - 1);
        }
    }
}
